#ifndef NAMEDPIPE_HPP_
# define NAMEDPIPE_HPP_

# include <fstream>
# include <string>

namespace wrappers {
namespace unix_utils {

/*!\class NamedPipe
 * \brief Wrapper for UNIX named pipe
 *
 * This class provide an object-oriented wrapper for UNIX named pipe
 */
class NamedPipe {
public:
  /*! Default constructor
   * \param filename : The file's name to use as a named pipe
   */
  NamedPipe(const std::string &filename);
  /*! Copy constructor
   * \param from : The NamedPipe object to copy
   */
  NamedPipe(const NamedPipe &from);
  /*! Virtual destructor */
  virtual ~NamedPipe();

  /*! Assignment operator overload
   * \param from : The NamedPipe object to copy
   */
  virtual NamedPipe &operator=(const NamedPipe &from);

  /*! Read data from the named pipe
   * \tparam T : the type of the data to read
   * \param data : a pointer on the object to fill with the read data
   * \param size : the size of the data to read (default = sizeof(T))
   * \return the parameter data
   */
  template<typename T> T *Read(T *data, size_t size = sizeof(T));

  /*! Write data into the named pipe
   * \tparam T : the type of data to write
   * \param dataToWrite : the data to write
   * \param size : the size of the data to write (default = sizeof(T))
   */
  template<typename T>
  void Write(const T *dataToWrite, size_t size = sizeof(T));

protected:
  virtual void OpenFileStream(); /*!< Open the file in a stream */

  std::string mFileName; /*!< The name of the file to use as a named pipe */
  std::fstream mPipeFile; /*!< A stream to the named pipe file */
};

template<typename T>
T *NamedPipe::Read(T *data, size_t size) {
  if (mPipeFile.rdbuf()->in_avail()) {
    mPipeFile.read(reinterpret_cast<char *>(data), size);
  }
  return data;
}

template<typename T>
void NamedPipe::Write(const T *dataToWrite, size_t size) {
  mPipeFile.write(reinterpret_cast<const char *>(dataToWrite), size);
  mPipeFile.flush();
}

}
}

#endif /* !NAMEDPIPE_HPP_ */
